/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tcloudclient;

import api.Beans.UserLogin;
import api.action.ActionPackageClient;
import api.exception.TCloudAplicationException;
import java.awt.TrayIcon;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import tcloudclient.UploadManager.ConnectionException;
import tcloudclient.UploadManager.ConnectionManager;
import tcloudclient.UploadManager.ConnectionManagerInterface;
import tcloudclient.actionManager.ActionExecutor;
import tcloudclient.contex.Context;
import tcloudclient.fileSystem.FileNode;
import tcloudclient.fileSystem.FileSystemManager;
import tcloudclient.fileSystem.FileSystemManagerInterface;
import tcloudclient.fileSystem.FileSystemStatusDataChangeLintenerInterface;
import tcloudclient.settings.ApplicationSettings;
import tcloudclient.settings.AutoLoginSetting;
import tcloudclient.settings.ConnectSettings;
import tcloudclient.settings.XmlLoaderSaver;
import tcloudclient.traySupport.TraySupport;
import tcloudclient.watchService.WatchService;
import tcloudclient.watchService.WatchServiceChangeData;
import tcloudclient.watchService.WatchServiceChangeType;
import tcloudclient.watchService.WatchServiceEventInterface;

/**
 *
 * @author Tomas
 */
public class Main extends javax.swing.JFrame {

    private WatchService watchService;
    private FileSystemManagerInterface fileSystemManager;
    private ConnectionManagerInterface connectionManager;
    private ActionExecutor actionExecutor;
    TraySupport systemTray;
    private SetupJDialog setupDlg;
    private Timer timer;
    private FileSystemStatusDataChangeLintenerInterface uploadDataChangeListener = new FileSystemStatusDataChangeLintenerInterface() {

        @Override
        public void dataChangeEventHandler(FileNode rootFileNode) {
            uploadChanges();
        }
    };

    /**
     * Creates new form Main
     */
    public Main() {
        initComponents();
        systemTray = new TraySupport(this);
        connectionManager = new ConnectionManager();
    }

    @Override
    public void setVisible(boolean b) {
        super.setVisible(b);
        try {
            init();
        } catch (ConnectionException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void initUser() {
        setupDlg = new SetupJDialog(this, true);
        setupDlg.setConnectioManager(connectionManager);
        setupDlg.setSetupFinish(new SetupFinishedInterface() {

            @Override
            public void setupSucessFul(UserLogin loginUser, String registredPath) {
                jLabelUserName.setText(loginUser.getUserName());
                jTextField1.setText(registredPath);
            }
        });

        setupDlg.setVisible(true);

        initFileSystem();
        if (Context.getInstance().getApplicationSettings().getConnectSettings() == null) {
            SetupDownloadJDialog setupDownDlg = new SetupDownloadJDialog(this, true);
            setupDownDlg.setVisible(true);

        }
        downloadChanges();

    }

    private void init() throws ConnectionException {
        AutoLoginSetting loginSetting = XmlLoaderSaver.loadLoginSetting();
        UserLogin login = null;
        if (loginSetting != null) {
            if (loginSetting.isAutologin()) {
                login = connectionManager.login(loginSetting.getUserName(), loginSetting.getPassword());
                jLabelUserName.setText(login.getUserName());
                XmlLoaderSaver.loadAppSettings();
                initFileSystem();
            } else {
                XmlLoaderSaver.loadAppSettings();
                initUser();
            }
        } else {
            initUser();
        }
        Context.getInstance().getApplicationSettings().addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if (evt.getPropertyName().equals(ApplicationSettings.PROP_CONNECT_SETTINGS)) {
                    initDownloadSetting((ConnectSettings) evt.getNewValue());
                    initUploadingSetting((ConnectSettings) evt.getNewValue());
                }
            }
        });
        initDownloadSetting(Context.getInstance().getApplicationSettings().getConnectSettings());
        initUploadingSetting(Context.getInstance().getApplicationSettings().getConnectSettings());

    }

    private void initDownloadSetting(ConnectSettings connectSettings) {
        if (connectSettings.isAutoDownload()) {
            if (timer != null) {
                timer.cancel();
            }
            timer = new Timer();
            timer.scheduleAtFixedRate(new TimerTask() {

                @Override
                public void run() {
                    downloadChanges();
                }
            }, connectSettings.getTimerInterval() * 60 * 1000, connectSettings.getTimerInterval() * 60 * 1000);
        } else {
            if (timer != null) {
                timer.cancel();
                timer = null;
            }
        }
    }

    private void initUploadingSetting(ConnectSettings connectSettings) {
        if (connectSettings.isAutoUpload()) {
            fileSystemManager.addDataChangeListener(uploadDataChangeListener);
        } else {
            fileSystemManager.removeDataChangeListener(uploadDataChangeListener);
        }
    }

    private void initFileSystem() {
        actionExecutor = new ActionExecutor();
        fileSystemManager = new FileSystemManager();
        actionExecutor.addActionListner(fileSystemManager.getActionListener());
        fileSystemManager.addDataChangeListener(new FileSystemStatusDataChangeLintenerInterface() {

            @Override
            public void dataChangeEventHandler(FileNode rootFileNode) {
                fileSystemInfoPanel1.setRootData(rootFileNode);
            }
        });
        fileSystemInfoPanel1.setRootData(fileSystemManager.getRootFolder());
        createWatchService();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jFileChooserSlednovanaSlozka = new javax.swing.JFileChooser();
        jPanel1 = new javax.swing.JPanel();
        jLabelSlednovanaSlozka = new javax.swing.JLabel();
        jTextField1 = new javax.swing.JTextField();
        jButtonSledovanaSlozkaVyber = new javax.swing.JButton();
        jTabbedPane1 = new javax.swing.JTabbedPane();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTextAreaChangeLog = new javax.swing.JTextArea();
        fileSystemInfoPanel1 = new tcloudclient.fileSystemInfo.FileSystemInfoPanel();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jButtonDownload = new javax.swing.JButton();
        jLabelUserName = new javax.swing.JLabel();
        jButton3 = new javax.swing.JButton();

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Log změn"));

        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("tcloudclient/Bundle"); // NOI18N
        jLabelSlednovanaSlozka.setText(bundle.getString("jLabelSlednovanaSlozka")); // NOI18N

        jTextField1.setEditable(false);

        jButtonSledovanaSlozkaVyber.setText("Vyber");
        jButtonSledovanaSlozkaVyber.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonSledovanaSlozkaVyberActionPerformed(evt);
            }
        });

        jTextAreaChangeLog.setColumns(20);
        jTextAreaChangeLog.setRows(5);
        jScrollPane1.setViewportView(jTextAreaChangeLog);

        jTabbedPane1.addTab("Změny", jScrollPane1);
        jTabbedPane1.addTab("Soubory", fileSystemInfoPanel1);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(jLabelSlednovanaSlozka)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 272, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jButtonSledovanaSlozkaVyber, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(0, 496, Short.MAX_VALUE))
                    .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 882, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabelSlednovanaSlozka)
                    .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jButtonSledovanaSlozkaVyber))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jTabbedPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 562, Short.MAX_VALUE)
                .addContainerGap())
        );

        jTabbedPane1.getAccessibleContext().setAccessibleName("tabChangeLog");

        jButton1.setText("Uloz nastavení");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jButton2.setText("Upload změn");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        jButtonDownload.setText("Download změn");
        jButtonDownload.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonDownloadActionPerformed(evt);
            }
        });

        jLabelUserName.setText("jLabel1");

        jButton3.setText("Nastavení");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jButton1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jButton2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jButtonDownload)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jButton3)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jLabelUserName)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton1)
                    .addComponent(jButton2)
                    .addComponent(jButtonDownload)
                    .addComponent(jLabelUserName)
                    .addComponent(jButton3))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jButtonSledovanaSlozkaVyberActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonSledovanaSlozkaVyberActionPerformed
        // TODO add your handling code here:
        jFileChooserSlednovanaSlozka = new JFileChooser();

        jFileChooserSlednovanaSlozka.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

        int vysledek = jFileChooserSlednovanaSlozka.showOpenDialog(this);
        if (vysledek == JFileChooser.APPROVE_OPTION) {
            File selectedFile = jFileChooserSlednovanaSlozka.getSelectedFile();

            jTextField1.setText(selectedFile.getAbsolutePath());
            ApplicationSettings applicationSetting = Context.getInstance().getApplicationSettings();
            if (applicationSetting == null) {
                applicationSetting = new ApplicationSettings();
            }
            applicationSetting.setRegisterDir(selectedFile);
            Context.getInstance().setApplicationSettings(applicationSetting);
            fileSystemManager = new FileSystemManager();
            if (watchService != null) {
                watchService.stopWatching();
            }
            createWatchService();
        }
    }//GEN-LAST:event_jButtonSledovanaSlozkaVyberActionPerformed

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        // TODO add your handling code here:
        XmlLoaderSaver.saveAppSettings();
        XmlLoaderSaver.saveFileSystemStatus();
    }//GEN-LAST:event_jButton1ActionPerformed

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        uploadChanges();
    }//GEN-LAST:event_jButton2ActionPerformed

    private void uploadChanges() {
        try {
            // TODO add your handling code here:
            boolean changes = connectionManager.uploadChange(fileSystemManager.getRootFolder());
            fileSystemManager.uploadedChangesSuccsessFul();
            if (changes) {
                systemTray.displayMessage("Update", "Local changes uploaded!", TrayIcon.MessageType.INFO);
            }
        } catch (TCloudAplicationException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ConnectionException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void jButtonDownloadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonDownloadActionPerformed
        downloadChanges();
    }//GEN-LAST:event_jButtonDownloadActionPerformed

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        // TODO add your handling code here:
        SetupDownloadJDialog setupDownDlg = new SetupDownloadJDialog(this, true);
        setupDownDlg.setVisible(true);
    }//GEN-LAST:event_jButton3ActionPerformed

    private void downloadChanges() {
        try {
            boolean update = connectionManager.isUpdate();
            if (update) {
                jButtonDownload.setEnabled(update);
                systemTray.displayMessage("Updates", "Updates are available", TrayIcon.MessageType.INFO);

                ActionPackageClient downloadChange = connectionManager.downloadChange(fileSystemManager.getRootFolder());
                watchService.stopWatching();
                actionExecutor.excuteActions(downloadChange);
                fileSystemInfoPanel1.setRootData(fileSystemManager.getRootFolder());
                systemTray.displayMessage("Updates", "Local files are updated", TrayIcon.MessageType.INFO);
                XmlLoaderSaver.saveFileSystemStatus();
                XmlLoaderSaver.saveAppSettings();
                createWatchService();

            } else {
                systemTray.displayMessage("Updates", "Nothing to donwload", TrayIcon.MessageType.INFO);
            }
        } catch (ConnectionException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void createWatchService() {
        watchService = new WatchService(Context.getInstance().getApplicationSettings().getRegisterDir().getAbsolutePath());
        watchService.addObserver(new WatchServiceEventInterface() {

            @Override
            public void event(WatchServiceChangeData data) {
                String text = data.getOperationType().toString();
                if (data.getOperationType() == WatchServiceChangeType.RENAME) {
                    jTextAreaChangeLog.append(text + ": from " + data.getFolder() + " to " + data.getNewFolderName() + "\n");
                } else {
                    jTextAreaChangeLog.append(text + ": " + data.getFolder() + "\n");
                }
            }
        });
        watchService.addObserver(fileSystemManager.getObserver());
        watchService.addObserver(systemTray.getWatchServiceObserver());
        watchService.start();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Windows".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new Main().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private tcloudclient.fileSystemInfo.FileSystemInfoPanel fileSystemInfoPanel1;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JButton jButtonDownload;
    private javax.swing.JButton jButtonSledovanaSlozkaVyber;
    private javax.swing.JFileChooser jFileChooserSlednovanaSlozka;
    private javax.swing.JLabel jLabelSlednovanaSlozka;
    private javax.swing.JLabel jLabelUserName;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JTextArea jTextAreaChangeLog;
    private javax.swing.JTextField jTextField1;
    // End of variables declaration//GEN-END:variables
}
